/**
 * 
 * Each time a client connects to the server, the server spawns a new ServerConnectionThread that listens for data from the client.
 * 
 * Author: Matthias Van Eeghem <matthias@van-eeghem.com>
 * All rights reserved.
 * 
 */

package com.bomberman.connection;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;

import com.bomberman.core.Field;
import com.bomberman.player.PlayerManager;

public class ServerConnectionThread extends Thread 
{
	// Hold the socket
	private Socket socket = null;
	// Hold the PrintWriter to send data to the client
	private PrintWriter out;
	// Hold the BufferedReader to read data from the client
	private BufferedReader in;
	// Hold the playerID that the server assigned to this thread
	private volatile int playerID;
	// Hold the above-laying connection manager
	private volatile ConnectionManager connectionManager;
	
	/**
	 * The constructor
	 * 
	 * @param connectionManager
	 * @param socket
	 */
	public ServerConnectionThread(ConnectionManager connectionManager, Socket socket)
	{
		this.socket = socket;
		this.playerID = -1;
		this.connectionManager = connectionManager;
	}
	
	/**
	 * Return the player ID for this thread
	 * 
	 * @return
	 */
	public int getPlayerID()
	{
		return playerID;
	}
	
	/**
	 * This method listens for data from the client 
	 */
    public void run() 
    {
    	try 
    	{
		    out = new PrintWriter(socket.getOutputStream(), true);
		    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		    
		    // Set up a CommunicationProtocol object
		    final CommunicationProtocol protocol = new CommunicationProtocol(connectionManager);
		    
		    // Assign an empty slot ID to this player
		    int playerID = PlayerManager.getEmptySlot();
		    
		    // Save the player id
		    this.playerID = playerID;
		    
		    // Send the field to the player
		    sendData(Field.getFieldAsString());
		    // Send all connected players
		    sendData(PlayerManager.getPlayerAsString());
		    
		    // Get the player name from the client
		    String playerName = in.readLine();
		    
		    // Handle a new connection
		    protocol.handleNewConnection(playerName, playerID);
		    
		    // Send the player id that we assigned to the player back to the client
		    sendData("YOUR_ID " + PlayerManager.getSpawnPositionForID(playerID).getRow() + " " + PlayerManager.getSpawnPositionForID(playerID).getColumn() + " " + playerID);
	 	  
		    try
		    {
			    String data = null;
				
			    // Keep reading data from the client
			    while ((data = in.readLine()) != null) 
				{
					protocol.handleData(data);
				}
		    }
		    catch (SocketException e)
		    {
			    out.close();
			    in.close();
			    socket.close();
		    }	
		}
    	catch (IOException e) 
    	{
		    e.printStackTrace();
		}
    }
    
    /**
     * This method sends data to the client
     * 
     * @param data
     */
	public void sendData(String data)
	{
		out.println(data);
		out.flush();
	}
}
